/* See LICENSE for copyright and terms of use */

import org.evtmng.timeline.Timeline;
import org.evtmng.util.List;
import org.evtmng.tween.Tween;
import org.evtmng.events.TweenListenerBroadcaster;
import org.evtmng.events.TweenEventInfo;

/**
 * <p>Uses the data from {@link org.evtmng.timeline.Timeline}.</p>
 *
 * @author Tay Ray Chuan
 */

class org.evtmng.timeline.TimelineManager {
	private var m_bcaster:TweenListenerBroadcaster;
	private var m_tl:Timeline;

	private var m_interval:Number;
	private var m_id:Number;
	private var m_time:Number;
	private var m_stopTime:Number;

	private var m_stack:List;

	public function TimelineManager(tl:Timeline) {
		m_bcaster = TweenListenerBroadcaster.instance();
		m_tl = tl;

		m_time = 0;
		m_interval = 100;
		m_id = null;
	}

	public function setTimeline(tl:Timeline):Void {
		m_tl = tl;
	}

	public function timeline():Timeline {
		return m_tl;
	}

	public function setTimeInterval(int:Number):Void {
		m_interval = int;
	}

	public function timeInterval():Number {
		return m_interval;
	}

	/**
	 * <p>Starts running the timeline from the time=0.</p>
	 */
	public function run():Void {
		runFromTime(0);
	}

	/**
	 * @param t
	 * <p>Starts running the timeline from the time <code>t</code>.</p>
	 */
	public function runFromTime(t:Number):Void {
		runFromTimeTo(t, m_tl.lastEnd());
	}

	/**
	 * @param t
	 * @param to
	 * <p>Starts running the timeline from the time <code>t</code>, and stops at the time
	 * <code>to</code>.</p>
	 */
	public function runFromTimeTo(t:Number, to:Number):Void {
		if(m_id!=null) {
			throw new Error("timeline is still running!");
		}
		m_time = t;
		m_stopTime = to;
		m_stack = new List();

		m_id = setInterval(this, "timelineRunner", m_interval);
	}

	private function timelineRunner():Void {
		var starts:Object = m_tl.tweensForStart(m_time);
		var ends:Object = m_tl.tweensForEnd(m_time);
		var i:String, f:Tween;

		var bc:Function = TweenListenerBroadcaster;
		var s_evt:String = bc.START_LSER_NAME;
		var r_evt:String = bc.RUN_LSER_NAME;
		var e_evt:String = bc.END_LSER_NAME;

		if(starts!=null) {
			for(i in starts) {
				f = starts[i];
				m_bcaster.dispatch(
					new TweenEventInfo(s_evt, f, m_time, this));
				m_stack.addItemWithId(f, f.id());
			}
		}
		var tweens:Object = m_stack;
		for(i in tweens) {
			f = tweens[i];
			m_bcaster.dispatch(
				new TweenEventInfo(r_evt, f, m_time, this));
		}
		if(ends!=null) {
			for( i in ends) {
				f = ends[i];
				m_bcaster.dispatch(
					new TweenEventInfo(e_evt, f, m_time, this));
				m_stack.removeItemWithId(f.id());
			}
		}

		if(m_time++>=m_stopTime) {
			stopTimeline();
		}
	}

	public function stopTimeline():Void {
		clearInterval(m_id);
		m_id = null;
	}
}
